******************************************************
smw hdma kit by d4s (c)2005
email: d4s[at]supernes[dot]de

programming: d4s
beta testing: iceman, someguy


user guide
******************************************************

this kit lets you assign various hdma effects to every level in super mario world.
you can either use the predefined effects, combine different effects or even create your very own ones.
no programming or assembler knowledge is required to use these effects.
however, you should have a basic idea of what the hexadecimal(short:hex) and the binary systems are.

a short reminder how these work:

valid numeric values: 		0-9	(10)
valid hexadecimal values:	0-f	(16)
valid binary values:		0-1	(02)

example:
if you want to represent the numeric value 255 in hex or binary, that would look as follows:

numeric:			255
hexadecimal:			ff
binary:				11111111

you will have to use different prefixes to differentiate between numerical, hexadecimal and binary values.
the following 3 are all able to represent one byte.
these are very important, so try to memorize them.
"$" means hexadecimal, "%" means binary, like this:

numeric				.db 000
hexadecimal			.db $00
binary				.db %00000000

im gonna call a certain binary byte bitflags, try to remember this aswell.


hdma is used to alter graphic settings or features while the screen is rendered on a per-scanline basis.
a scanline is a horizontal, 1 pixel wide line on the screen.
hdma is capable of producing color gradients, wavey backgrounds and numerous other things.
its appearance on screen is controlled by so-called hdma tables.

ok, so what you will do to enable these is set 4 bytes of configuration per level.
1 byte of binary bitflags to enable or disable effects and 3 bytes of hexadecimal values to
select the appropriate hdma tables for the effects.

first, you'll want to properly set up your hdma kit.
to do this, proceed as follows:


1. patch the included *.ips file to a clean, unmodified Super Mario World (U) rom. 
the rom MUST NOT have a $200 byte header.
if it has one, use snestool or a hexeditor to get rid of the first $200 bytes of the rom file.
patching will install the 1000+ lines of assembler code and various other stuff, including
the fastrom conversion responsible for eliminating slowdowns and a new intro screen.
rename the rom file to "smw.smc", this is required for the linker to work properly.
start up the rom in an emulator. if it doesnt work or the checksum is bad,
you have made a mistake, possibly by starting out with a corrupt rom image.


2. edit the file levelattributes.txt to bind effects to the levels of your choice.
i will get to that in detail later.

3. execute the included linker.bat file to compile your changes to levelattributes.txt
into the rom. if executing this file results in an error, watch closely what the error report says.
it contains information on which line of your textfile the error occured.
most likely, you mistyped something while editing any files.
the error "background file size and rom file size don't match" most likely means your rom still has
an header, which it shouldn't, of course.

if everything went fine, there will be a new rom in the directory called smw_hdma.smc.
this file is the compiled rom that contains the changes you made.
it has a $200 byte header and can directly be edited using lunar magic.



warning: if you want to make changes to the hdma settings of the rom after you edited it with lunar magic,
you'll have to remove its header and rename it to smw.smc again.
sorry, theres no way around that currently.


here's a short reference list of things i altered in the rom.
- speeded the whole game up to prevent slowdowns (fastrom conversion)
- added a flexible hdma handler(this is the reason you downloaded this, after all)
- added a new intro screen, removed old nintendo logo and startup sound
- moved the priority of several sprites up one level, this is required for color gradients.
  you will have to set the priority bits for foreground tiles that should appear in front of them.(pipes etc)
  affected sprites are:
  	piranha plant
  	pipe-lakitu
  	the wooden stakes in some boss levels
  	the smoke in yoshis house

- screen brightness decrease in pause mode (i always hated that the game didnt have a visual indication of being in pause mode, thats why i added it)


now, let's proceed to the levelattributes.txt file modification.
open it and and you will see a long list in the following format:

;level $0000
	.db %00000000
	.db $00
	.db $00
	.db $00

each of these 5-line snippets represents the configuration needed for a single level.
let's go through it line by line:

;level $0000

this obviously is the level number.
the level number indicator is for your information only, it's not actually compiled into the rom
so changing this will have no effect apart from probably confusing you.
if you delete any lines in this textfile, it will mess up the configuration order of the levels, so
just don't.


the level numbers directly represent the level numbers present in lunar magic and range from $0000 to $01ff.
the current level number can also be found at ram adress $7e011e.

.db %00000000

these are the bitflags used to turn various hdma effects on or off.
you can imagine them to be like dipswitches, they can either be switched off or on
by writing 0 or 1 to them.
each of these 8 entries is called a bit.
a bit holding the value 0 is called "clear", while a bit holding
the value 1 is called "set".
these bits are counted from right to left.
that means the rightmost bit is bit0 while the leftmost one is bit7.

heres a small reference in case you arent used to these:

bit number:	      76543210
bitflags:	 .db %00000000


heres what the bitflag configuration looks like:

bit 0 set=enable hdma
bit 1 set=enable hdma cgadsub
bit 2 set=enable h-scroll hdma on bg1
bit 3 set=enable h-scroll hdma on bg2
bit 4 set=enable v-scroll hdma on bg1
bit 5 set=enable v-scroll hdma on bg2
bit 6 set=enable multilayer scrolling on bg2
bit 7 set=unused


and here is a more detailled explantation:

bit0: enable hdma
this is the main switch, so to speak.
always has to be set to enable hdma effects in this level.
if its not set, no effects will be processed, no
matter which other bits are set.


bit1: enable hdma cgadsub
this one enables color gradients, color addition and substraction effects
in a level.
in addition to this bitflag, you'll have to specify the hdma table
that should be used to produce the color effects for this level.
the tables itself determine to which layer(background, sprites, foreground etc)
the color gradient is applied to, so you don't have to set that up here.
refer to the hdma effects tables list.

to make these color gradients possible, i had to alter the priority of some sprites. (namely piranha plants, pipe-lakitu,
the wooden stakes in some boss levels and the smoke in yoshis house)
due to this, they will now appear IN FRONT of bg1 rather than behind it.
THIS IS NOT A BUG!
to move them back behind pipes or other objects, you will have to set the priority bits of the tiles that should appear in front of these sprites in the lunar magic 16x16 tile editor.
keep in mind that some sprites (pipe-lakitu, for example) will fall all the way through a pipe to the bottom of the screen if theyre hit,
so you may want to set the priority of all the tiles below them, aswell.
if you choose to have color gradients in a certain level, dont put graphics on layer 2 at all if the level has climbing koopas or the brown stompers.(iggys castle, for example)
apart from that, everything should be fine.
please keep in mind that layering and priority problems are not programming bugs, they surface because the game wasnt meant to have
all these effects in the first place, so you will have to do some tweaking with the tile priorities here and there to be able to get the most out
of this.

some preset color gradient tables will have effects enabled on the sprite layer.
however, only sprite using palettes 4-7 will actually be affected by the color processing.
again, this is no bug, but a hardware limitation of the snes.



IMPORTANT2:
using hdma color gradient tables will override the normal background color in levels were the background is not fully covered with
tiles.
solution: either use/design a color gradient table that affects the background color or have a full image on bg2 to prevent the background color from showing through at all.
when designing color gradient hdma tables(see the advanced section), keep in mind that the first color entry can be defined by changing the levels background color in lunar magic.
the color table will fade out at level end, but it will not fade back in.
this is the way i designed it, so dont bother reporting this as a bug.
 

bit2: enable h-scroll hdma on bg1
used to enable foreground (layer 1) horizontal morphing and scrolling effects.
from wavey backgrounds to whacky moving levels to 3d-scrolling effects,
there is a wide range of uses for this one.
in addition to this bitflag, you'll have to specify the hdma table
that should be used to produce the scrolling effects for this level.
refer to the hdma effects tables list.


bit3: enable h-scroll hdma on bg2
works similar to bit2, but for the background(layer 2).


bit4: enable v-scroll hdma on bg1
this is equivalent to bit2, but enables vertical scrolling effects instead of
horizontal ones.
you can only have either horizontal or vertical scrolling effects enabled at the same time,
not both.
v-scroll bits always have priority, so if both bg1 h-scroll and and bg1 v-scroll bits are set,
only v-scroll effects will actually be processed.

bit5: enable v-scroll hdma on bg2
same as bit 4, but operates on bg2(background) instead of bg1.

bit6: enable multilayer scrolling on bg2
this effect is exclusive to bg2.
you can use it to change the background scrolling-speed 112 times per frame, enabling you
to produce pseudo-3d effects and the like.
if bit 5(v-scroll bg2) is set, bit6 has no effect.
as stated above, v-scroll effects always have priority over h-scroll ones.
if you want to use this, you'll have to set bit2(horizontal scroll) aswell.


here are some exaple bitflag settings, so you get used to them:

.db %00000011		<-enable color addition effect only.

.db %01001111		<-enable color addition effect, horizontal scrolling on bg1 and horizontal multilayer scrolling on bg2.

.db %00110001		<-enable vertical scrolling effects on both bg1 and bg2 (foreground and background)
			sidenote:
			because v-scroll effects always have priority if set, .db %00110001 and .db %01111101 will produce
			the exact same effects mentioned above.(bits 2,3 and 6 are ignored)
			
			
next up is the hdma table number setup.thats the 3 bytes below the bitflags:

1.) bg1 scrolling effects table number:		.db $00
2.) bg2 scrolling effects table number:		.db $00
3.) color gradient effects table number:	.db $00

these are pretty easy, actually. they determine which hdma table is used for which effect.
the first one is responsible for bg1 scrolling effects, the second one does the same for bg2 and finally,
the last one selects the table used for color gradient effects.
as a rule of thumb, i've put scrolling tables in slots $01-$0f and color gradient effects in slots $10-$1f.
don't use scrolling tables for color gradients and vice versa, this could crash the game.

below is a list of present hdma effect tables:


table entries $01-$0f = bg1/bg2 scroll effects:


slot	description
$00=	an initialization table, not an actual effect per se. can be used to do scrolling effects, though.
$01=	a scroll table that simulates water movement. try it out on bgs 1 and 2 for water levels.
$02=	a scroll table that simulates hot air. cool for lava levels in conjunction with a red color gradient.
$03=	parallax scrolling clouds and a moving 3d-ground on bg2 can be generated with this table. use in conjunction with the "multilayer scroll"-bitflag. try it out with donkey kong countries level 1 bg tileset.
$04=	two parallax scrolling bars, needs the "multilayer scroll"-bitflag. graphics can be hard to get right for this one, but looks awesome if done correctly.
$05=	normal sinewaves for bg1 or 2.
$06=	linear waves for bg1 or 2, looks funky.
$07=	very small waves, good for vertical scroll effects.
$08=	free entry
$09=	free entry
$0a=	free entry
$0b=	free entry
$0c=	free entry
$0d=	free entry
$0e=	free entry
$0f=	free entry


table entries $10-$1f = cgadsub/color gradient effects:

slot	description
$10=	puts a shading gradient on the bg3 statusbar
$11=	a blue sky fading to white
$12=	green gradient, good for water levels
$13=	top: dark fadeout. bottom: red gradient, best used in lava levels
$14=	a simple fade to white for bg1 and 2.
$15=	fade to white on top and bottom.
$16=	25% scanlines on bg1 and bg2
$17=	fades from white to blue to white, has that icey feeling to it.
$18=	fades the background behind the statusbar and the bottom of the screen to dark. if you want to keep it simple, this one will add subtle visual improvement.
$19=	blue gradient, fine for underwater levels
$1a=	this yellow to white gradient could come in handy for desert levels
$1b=	a red to orange sunset-like gradient for the background color only. doesn't look particularly good.
$1c=	background color gradient, fade level bg color to green. proper background color has to be set within lunar magic to function correctly.
$1d=	background color gradient, fade level bg color to yellow. proper background color has to be set within lunar magic to function correctly.
$1e=	background color gradient, fade level bg color to red. proper background color has to be set within lunar magic to function correctly.
$1f=	free entry



you can add your own tables to this list by modifying the link.txt file.
i will cover that in the advanced section.


we are at the end of the basic user guide.
to get you started, here are some preset effects you can copy&paste into your levelattributes.txt and play around with.
these are just examples to give you some ideas. be sure to read the advanced section aswell to be able to create your
own hdma tables.




Level Config: desert
a yellow to white fade on bg1 and bg2 plus
two different v-scroll effects simulating rising hot air

;**************-cut me here-**************
	.db %00110011	;enable color gradient, bg1 & bg2 v-scroll
	.db $07		;bg1 v-scroll effects table: small waves
	.db $05		;bg2 v-scroll effects table: normal sine
	.db $1a		;color gradient: yellow to white fade
;**************-cut me here-**************




Level Config: underwater
a blue to blue fade on bg1 and bg2 plus
two different h-scroll effects simulating moving water

;**************-cut me here-**************
	.db %00001111	;enable color gradient, bg1 & bg2 h-scroll
	.db $01
	.db $05
	.db $19
;**************-cut me here-**************



Level Config: shaded status bar
spices up the otherwise plain looking status bar

;**************-cut me here-**************
	.db %00000011	;enable color gradient
	.db $00
	.db $00
	.db $10
;**************-cut me here-**************




Level Config: shaded status bar 2
this actually doesnt shade the status bar itself, but
fades out the background behind the statusbar to make it
easier to read. 
also adds a small fadeout to the bottom of the screen.

;**************-cut me here-**************
	.db %00000011	;enable color gradient
	.db $00
	.db $00
	.db $18
;**************-cut me here-**************




Level Config: scanlines
a nice effect that puts scanlines of 25% brightness
on bg1 and bg2.
;**************-cut me here-**************
	.db %00000011	;enable color gradient
	.db $00
	.db $00
	.db $16
;**************-cut me here-**************



Level Config: lava
a black to red fade on bg1 and bg2 plus
v-scroll effects simulating rising hot air

;**************-cut me here-**************
	.db %00110011	;enable color gradient, bg1 & bg2 v-scroll
	.db $07		;bg1 v-scroll effects table: small waves
	.db $07		;bg2 v-scroll effects table: normal sine
	.db $13		;color gradient: yellow to white fade
;**************-cut me here-**************



Level Config: 3d sea
this effect is similar to the one used by donkey kong country 2
in level 1.
the top half of the screen is scrolling at various rates to mimic cloud movement.
the bottom half scrolls at different rates, too, but basing on marios movement to
create some depth.
has a green fade in on top of that.


;**************-cut me here-**************
	.db %01001011	;enable color gradient, bg2 multilayer scroll
	.db $00		
	.db $03		;bg2 multilayer scroll effects table: 3d clouds/ground
	.db $12		;color gradient: green fade in
;**************-cut me here-**************




Level Config: 3d bars
this effect is similar to the one used by donkey kong country 2
in the underwater levels.
there are two pseudo-3d bars on bg2.
however, they are limited to horizontal 3d-movement.
graphics for the can be hard to get right, but try it nevertheless,
it looks awesome if you do it correctly.


;**************-cut me here-**************
	.db %01001001	;enable bg2 multilayer scroll
	.db $00		
	.db $04		;bg2 multilayer scroll effects table: 3d bars
	.db $00		
;**************-cut me here-**************







advanced section

hdma table creation:
this section requires you to have fully read and understood the above introduction.
there are three types of hdma tables:

1.) color gradient tables
2.) wavescroll tables
2.) multilayer scroll tables

first, have a look at the existing *.tbl files in the /data directory.
if you want to create additional table files, put them into the /data directory and link them properly
in the link.txt file.
to do so, just look for a free slot in link.txt, for example this one:

SmwHdmaEffectTable1b:

next, add your file below it, like this:

SmwHdmaEffectTable1a:
	.INCLUDE ".\\data\\smwyellowadditioncgadsub.tbl"

by executing linker.bat, your new table is compiled into the rom.

the current limit is $2f tables.
the theoretical maximum is $ff, but you'd have to extend the pointertable in link.txt to
use that.


next up is color gradient table editing.
the format of the tables is as follows:

the first two bytes contain the mainscreen and subscreen designation for that level.
you can experiment with them, but i suggest to leave them at the default values of:

	.db %00010111		;mainscreen designation
	.db %00000000		;subscreen designation


the "real" table defining the color gradient starts after this.
this is what a standard table entry looks like:

	.db $01			;scanline count
        			
        	.db $33		;cgadsub config
		.db $e0		;color data

let's discuss the scanline count first.
it determines how many scanlines to count until the next entry is processed.
usually, values range from $01 to $7f.
$00 terminates the table, and values over $7f are repeat mode, which
i don't prefer, but you can try it if you like.

cgadsub is the configuration of the table entry.
use the windows scientific calculator to convert its values between hex and binary.

bits 0-5 select which layers the color effect should be applied to.
set these corresponding bits to enable the desired layers:

	bit5	background color
	bit4	sprites
	bit3	bg4-not used
	bit2	bg3
	bit1	bg2
	bit0	bg1
	
	
bit7 selects if the color data should be added or substracted from the selected layers.

bit6 selects if the result of this addition or substraction should be divided by 2.
this is useful if you dont want all the colors to fade to white or black, try it out yourself.

sidenote: bit4 selects the sprite layer, but only sprites using palettes 4-7 will actually be affected by the color processing.
this is a hardware limitation of the snes.


and now comes the tricky part, the color data.
this value obviously contains the color that is to be added or substracted from the layers selected by
the cgadsub value.
however, you dont write direct rgb values here.
instead, you select the r,g,b colors individually and assign them a certain intensity.

again, use the scientific calculator to convert from hex to binary and vice versa or
write them as binary values directly.
the format is as follows:

	bit7	enable writing intensity to blue
	bit6	enable writing intensity to green
	bit5	enable writing intensity to red
	
	bit0-4	intensity
	
for example, this is what the primary full intensity colors looks like(binary/hex):

	color	binary		hex
	blue	.db %10011111 / .db $9f
	green	.db %01011111 / .db $5f
	red	.db %00111111 / .db $3f
	
	white	.db %11111111 / .db $ff
	black	.db %11100000 / .db $e0
	
and here's whats tricky about them:
each of the colors will keep their intensity until you select them the next time.

say, you want to do some effect that has a pink area and a green area right below it, how would you do that?
usually, you'd first select the color pink (.db %10111111, blue and red full intensity), then
select the color green in a later entry (.db %01011111).

however, this will NOT produce a green field, but a white full intensity one.
why?
because you first wrote full intensity to blue and red, then full intensity to green,
resulting in all 3 colors being full on.

what you have to do to create the desired effect is write pink first(.db %10111111, blue and red full intensity),
then set blue and red to zero intensity (.db %10100000) and after that set green to full(.db %01011111).
that means you have to use three entries to create 2 colors.
if you want to display a colour composed of 3 different red, green and blue intensities, you'd therefore
have to use 3 table entries for that.

actually, it's very simple, just a rather unusual concept.
i suggest to use the preset tables as references while you're learning.

IMPORTANT:
every table has to be terminated with a sequence of 3 ".db $00", then 3 ".db $ff".
look it up in the preset files if you are unsure.




ok, now on to the hdma scroll tables.
these are actually pretty easy.
its just a long series of bytes, each byte being an entry defining how much the scrolling offset of
the current scanline should be displaced.
they use a fixed scanline count of 2, that means that each byte
actually sets the scrolling offset for two scanlines at once,
this was done to limit cpu usage.
these tables wrap around, so each byte doesnt go to a fixed scanline.
similar to the color gradient tables, these are terminated with a sequence of 3 $ff aswell.

a normal, very small sinewave would look somewhat like this:
	.db $00
	.db $01
	.db $02
	.db $01
	
	.db $ff
	.db $ff
	.db $ff

thats it, a fully functional hdma scrolltable.
keep on experimenting to find other cool effects.


last but not least i'm gonna tell you something about the multilayer scroll tables.
these are similar to the above-mentioned wavescroll tables, with four important differences.

1.) they dont wrap around, that means each byte always goes to the same equivalent 2 scanlines.
2.) each byte actually contains 2 values, a nybble each.
3.) their initial scanline count value depends on the current vertical scroll value of bg2
4.) they can only be applied to bg2(background) and only in horizontal scroll mode.


here's an outline of the format:

as i said, each byte holds 2 values each 1 nybble in size.
the upper nybble controls constant movement.
this results in a constant scrolling process, no matter if bg2 is actually scrolling or not.
its useful for independantly moving clouds and things like that.
heres an example:

	.db $0x
	.db $4x
	.db $3x
	
"x" means "don't care" in this case.


the lower nybble does the same thing, but only while bg2 is scrolling(eg. mario is moving).
in addition to that, the scrolling direction is affected by bg2 scrolling aswell, which results
in very cool pseudo-3d-effects.

	.db $x0
	.db $x1
	.db $x2
	.db $x3
	.db $x4
	.db $x5
	
this, for example, would create a 12 pixel tall 3d-scrolling field on bg2.
your graphics have to be very carefully designed to look good with this feature, though.

of course, you can also combine lower and upper nybble to have constant and 3d-movement on the same scanlines.
be careful not to stress this feature too much, though, it will result in slowdowns.
this feature can only be used on bg2.




custom block/external code support:
although i dont like blocktool very much, i've included an option to control the hdma effects by external code.

basically, it works exactly the same like the levellist, there are 4 bytes of configuration (1 byte bitflags, 3 bytes hdma table number),
with one exception:
you have to set bit7 of the bitflags, this is the override flag that will fetch the config bytes directly from
ram and not from the levellist in the rom.
these 4 bytes are cleared each time a level is exited.

here's a short description of the needed variables:

Variable Name				Location	configuration
SmwHdmaBlocktoolBitflags		$7e012c		;blocktool settings flag
							;bit 0 set=enable hdma
							;bit 1 set=enable hdma cgadsub
							;bit 2 set=enable hdma wave on bg1
							;bit 3 set=enable hdma wave on bg2
							;bit 4 set=bg1 v-scroll
							;bit 5 set=bg2 h-scroll
							;bit 6 set=enable multilayer scrolling on bg2
							;bit 7 set=override level attribute table and load hdma config from the following vars

SmwHdmaBlocktoolBg1TableNumber		$7e012d		;bg1 scroll hdma table
SmwHdmaBlocktoolBg2TableNumber		$7e012e		;bg2 scroll hdma table
SmwHdmaBlocktoolCgadsubTableNumber	$7e012f		;color gradient hdma table


hint:
writing #$81 to SmwHdmaBlocktoolBitflags instantly terminates all hdma effects, #$80 halts them.

heres an example program you can use to make a custom block that instantly disables all hdma effects.
(watch out, original main/subscreen settings will not be restored automatically upon external code intervention,
you'll have to do this yourself if required.):


;********************************
CustomBlockDisableHdma:
	php			;push cpu flags
	sep #$20		;set a/mem to 8bit
	lda #$81		;load bitflags, blocktool override bit set, hdma enable bit set
	sta $7e012c		;store in SmwHdmaBlocktoolBitflags
	plp			;pull cpu flags
	rts			;return
;********************************
see, its that easy.
keep in mind that i dont use custom blocks myself, so this feature is somewhat untested, although it should work fine.

